import ast
import datetime
import json

from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.http import HttpResponseRedirect, QueryDict, HttpResponse
from django.shortcuts import render, get_object_or_404
from django.urls import reverse_lazy
from django.views.generic import CreateView, ListView, UpdateView, DeleteView, TemplateView, DetailView
from django.views.generic.base import View

from accounts.models import CustomUser, Department_Mode
from assets.forms import ProjectForm
from utils.tools import mysql_connection_raw_query_sql
from .models import (IDC, Host, Project, Service, HostRecord, ProductLine, Server_System, SERVER_STATUS, ProjectSwan,
                     ProjectUser)

from django.conf import settings

ZABBIX_ON = settings.ZABBIX_ON


class IdcCreateView(CreateView):
    """ 创建Idc """
    success_url = reverse_lazy('idc_list')
    template_name = 'assets/idc_create.html'
    model = IDC
    fields = ('name', "bandwidth", "operator", 'type', 'linkman', 'phone', 'network', 'address', 'comment')

    def form_valid(self, form):
        #         init = request.GET.get("init", False)
        if ZABBIX_ON:
            # TODO
            """
            if zabbix_on:
                ret = zabbix_group_add(idc_name)
                if ret != 1:
                    emg = '添加zabbix主机组 %s 失败!' % idc_name
                    return my_render('assets/idc_add.html', locals(), request)
            if not init:
                return HttpResponseRedirect("/assets/idc_list/")
            else:
                return HttpResponseRedirect('/assets/server/type/add/?init=true')      # 添加项目 | Add business.
        """
        return super().form_valid(form)


class IdcListView(ListView):
    """ Idc 列表"""
    template_name = 'assets/idc_list.html'
    model = IDC
    context_object_name = "idc_list_objs"


class IdcUpdateView(UpdateView):
    """ IDC更新 """
    model = IDC
    fields = ['name', "bandwidth", "operator", 'type', 'linkman', 'phone', 'network', 'address', 'comment']
    success_url = reverse_lazy('idc_list')
    template_name = 'assets/idc_update.html'


class IdcDeleteView(TemplateView):
    """ Idc 删除 """
    success_url = reverse_lazy('idc_list')

    def get(self, request, *args, **kwargs):
        idc = get_object_or_404(IDC, pk=kwargs.get("pk"))
        # todo
        """     
        idc_name = idc.name
        if zabbix_on:
            zabbix_group_del(idc_name) 
        """
        idc.delete()
        return HttpResponseRedirect(self.success_url)


class HostCreateView(CreateView):
    """ 创建主机视图 """
    success_url = reverse_lazy('host_list')

    template_name = "assets/host_create.html"
    model = Host
    fields = ("node_name", "idc", "room_number", "eth1", "eth2", "mac", "internal_ip", "room_number", "cabinet",
              "server_cabinet_id", "number", "projects", "service", "env", "status",
              "cpu", "hard_disk", "memory", "system", "system_cpuarch", "vm", "services_code",
              "brand", "guarantee_date", "server_sn", "idle", "editor")

    def form_valid(self, form):
        #  如果是虚拟机,则输入物理机ip
        physics = QueryDict(self.request.body).get('physics', False)

        # form = form.save(commit=False)
        form.mac = str(self.request.POST.getlist("mac")[0]).replace(':', '-').strip(" ")
        status = QueryDict(self.request.body).get('status', False)  # 1 表示已经安装操作系统
        if physics:
            # 通过物理机ip 找到父主机,虚拟机关联到父主机(自关联)
            physics_host = get_object_or_404(Host, eth1=physics)
            form.vm = physics_host
            form.type = 1  # 虚拟机类型
        else:
            form.type = 0  # 物理机
        # todo 拆分以信号实现分离
        """ 
        if ZABBIX_ON and status:
            zabbix_host_add(request)
        """

        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        projects = Project.objects.all()
        services = Service.objects.all()  # 基础服务，如nginx, haproxy, php....
        kwargs.update(projects=projects)
        kwargs.update(services=services)
        return super().get_context_data(**kwargs)


class HostUpdateView(UpdateView):
    """ 主机更新 """
    SELECT_SQL = 'SELECT * FROM assets_host where id =%s'
    INSERT_SQL = 'INSERT INTO  `assets_hostrecord` (`user`,  `content`,`time`,  `host_id`) VALUES ( %s, %s, %s ,%s ) '
    success_url = reverse_lazy('host_list')
    template_name = 'assets/host_update.html'
    model = Host
    fields = ("node_name", "idc", "room_number", "eth1", "eth2", "mac", "internal_ip", "room_number", "cabinet",
              "server_cabinet_id", "number", "projects", "service", "env", "status",
              "cpu", "hard_disk", "memory", "system", "system_cpuarch", "vm", "services_code",
              "brand", "guarantee_date", "server_sn", "idle", "editor")

    def get_context_data(self, **kwargs):

        pk = self.kwargs.get("pk")

        host = get_object_or_404(Host, pk=pk)

        project_all = Project.objects.all()
        project_host = host.projects.all()

        service_all = Service.objects.all()
        service_host = host.service.all()

        # 过滤出没有选择的服务和项目
        projects = [p for p in project_all if p not in project_host]
        services = [s for s in service_all if s not in service_host]
        kwargs.update(projects=projects)
        kwargs.update(services=services)

        return super().get_context_data(**kwargs)

    def get_initial(self):

        pk = self.kwargs.get("pk")

        # 获取修改前的数值
        rest_data = mysql_connection_raw_query_sql(self.SELECT_SQL, args=[pk])
        self.kwargs.update({"before_update_date": rest_data})

        return super().get_initial()

    def get_success_url(self):
        pk = self.kwargs.get("pk")
        before_update_date = self.kwargs.get("before_update_date")

        # 获取修改后的数值
        after_update_date = mysql_connection_raw_query_sql(self.SELECT_SQL, args=[pk])
        username = self.request.user.username

        # 判断修改前后,哪些值发生了变化
        sh_items = {
            key for key in before_update_date.keys()
            if key in after_update_date and
               before_update_date[key] != after_update_date[key]
        }

        # 更新到数据库
        now_time = datetime.datetime.now()
        for key in sh_items:
            text = "%s 由%s 更改为 %s" % (key, before_update_date[key], after_update_date[key])
            sql = self.INSERT_SQL
            args = (username, text, now_time, pk)
            mysql_connection_raw_query_sql(sql, args, sql_type='INSERT')

        return super().get_success_url()

    def form_valid(self, form):
        host = get_object_or_404(Host, pk=self.kwargs.get("pk"))

        #  如果是虚拟机,则输入物理机ip
        physics = QueryDict(self.request.body).get('physics', False)

        # form = form.save(commit=False)
        form.mac = str(self.request.POST.getlist("mac")[0]).replace(':', '-').strip(" ")
        status = QueryDict(self.request.body).get('status', False)  # 1 表示已经安装操作系统
        if physics:
            # 通过物理机ip 找到父主机,虚拟机关联到父主机(自关联)
            physics_host = get_object_or_404(Host, eth1=physics)
            form.cleaned_data["vm"] = physics_host
            form.cleaned_data["type"] = 1  # 虚拟机类型
        else:
            form.cleaned_data["vm"] = None
            form.cleaned_data["type"] = 0  # 物理机
        # todo 拆分以信号实现分离
        """ 
        if ZABBIX_ON and status:
            zabbix_host_add(request)
        """

        return super().form_valid(form)


class HostDetailView(DetailView):
    template_name = 'assets/host_detail.html'
    model = Host

    def get_context_data(self, **kwargs):
        # 主机修改记录
        pk = self.kwargs.get('pk')
        # host_record = HostRecord.objects.filter(pk=pk).order_by('-time')
        host = get_object_or_404(Host, pk=pk)
        host_record = host.hostrecord_set.order_by('-time')[:50]
        kwargs.update({"host_record": host_record})
        kwargs.update({"host": host})
        return super(HostDetailView, self).get_context_data(**kwargs)


class HostDeleteView(View):
    """  删除主机视图 """

    def get(self, request, *args, **kwargs):
        pk = self.kwargs.get('pk')
        host = get_object_or_404(Host, pk=pk)
        host.status = 3
        host.eth1 = ''
        host.eth2 = ''
        host.node_name = str(pk)
        host.internal_ip = ''
        host.system = ''
        host.system_cpuarch = ''
        host.system_version = ''
        host.cabinet = ''
        host.server_cabinet_id = 0
        host.env = ''
        host.number = ''
        host.switch_port = ''
        idc_ = IDC.objects.filter(name=u"报废库房")
        if idc_.exists():
            idc_ = idc_.first()
        else:
            idc_ = None
        host.idc = idc_
        host.projects.clear()
        host.service.clear()
        host.save()
        return HttpResponseRedirect(reverse_lazy('host_list'))


''' 
def host_del_batch(request):
    """ 批量删除主机 """
    ids = str(request.POST.get('ids'))
    for uuid in ids.split(','):
        host = get_object_or_404(Host, uuid=uuid)
        host.status = 3
        host.eth1 = ''
        host.eth2 = ''
        host.node_name = host.uuid
        host.internal_ip = ''
        host.system = ''
        host.system_cpuarch = ''
        host.system_version = ''
        host.cabinet = ''
        host.server_cabinet_id = 0
        host.env = ''
        host.number = ''
        host.switch_port = ''
        host.idc = IDC.objects.get(name=u'报废库房')
        host.projects.clear()
        host.service.clear()
        host.save()
    return HttpResponseRedirect('/assets/host_list/')
'''


class HostListView(TemplateView):
    """ 主机列表 """
    template_name = 'assets/host_list.html'

    def get_context_data(self, **kwargs):
        hosts = Host.objects.all().order_by("-eth1")
        server_list_count = hosts.count()

        pagination = Paginator(hosts, 1, 2)
        page = self.request.GET.get('page', 1)  # 页数
        try:
            hosts_pagination = pagination.page(page)
        except PageNotAnInteger:
            hosts_pagination = pagination.page(1)
        except EmptyPage:
            hosts_pagination = pagination.page(pagination.num_pages)

        idcs = IDC.objects.filter()
        lines = ProductLine.objects.all()
        server_types = Project.objects.all()  # 所有项目
        services = Service.objects.all()
        brands = Server_System
        server_status = SERVER_STATUS
        physics = Host.objects.filter(vm__isnull=True).count()
        vms = Host.objects.filter(vm__isnull=False).count()

        context_data = {
            "hosts": hosts,
            "idcs": idcs,
            "lines": lines,
            "server_types": server_types,
            "services": services,
            "brands": brands,
            "server_status": server_status,
            "server_list_count": server_list_count,
            "physics": physics,
            "vms": vms,
            "hosts_pagination": hosts_pagination,
        }
        kwargs.update(context_data)
        return super(HostListView, self).get_context_data(**kwargs)


class T(TemplateView):
    page_query_param = 'page'
    template_name = 'test_pagenayion.html'
    page_size = 5

    def get_context_data(self, **kwargs):
        quert_set = HostRecord.objects.all()
        pagination = Paginator(quert_set, 3, 2)
        page = self.request.GET.get('page', 1)  # 页数
        try:
            customer = pagination.page(page)
        except PageNotAnInteger:
            customer = pagination.page(1)
        except EmptyPage:
            customer = pagination.page(pagination.num_pages)

        kwargs.update({"customer_list": customer})

        return super(T, self).get_context_data(**kwargs)


# from django.core.paginator import InvalidPage
# from django.core.paginator import Paginato

# todo 项目相关人添加有bug,  只能是研发
class ProjectCreateView(TemplateView):
    """ 添加项目 """

    # todo  status = check_auth(request, "add_project")
    template_name = ""
    form = ProjectForm

    def get(self, request, *args, **kwargs):
        form = self.form()

        user_list = CustomUser.objects.all()

        user_group = []
        context = {'form': form, "user_lit": user_list, "user_group": user_group}
        return render(request, 'assets/project_create.html', context)

    def post(self, request):
        form = self.form(request.POST)
        init = request.GET.get('init', False)  # todo
        if form.is_valid():
            form.save()
            project_name = form.cleaned_data.get("project_name")
            """
            if settings.ZABBIX_ON:
                ret = zabbix_group_add(project_name)
                if ret == 0:
                    pass
            if not init:
                return HttpResponseRedirect("/")  # todo 重定向到项目列表
            else:
                return HttpResponseRedirect(reverse_lazy('host_create'))  # 重定向到添加主机  """
            return HttpResponseRedirect(reverse_lazy('project_list'))
        context = {'form': form}
        return render(request, 'assets/project_create.html', context)


class ProjectListView(TemplateView):
    """  项目列表 """
    # todo project_auth
    template_name = 'assets/project_list.html'

    def get_context_data(self, **kwargs):
        project_list = Project.objects.all()
        swan_all = ProjectSwan.objects.all()  # 发布系统字段
        kwargs.update({"project_list": project_list, 'swan_all': swan_all})

        return super().get_context_data(**kwargs)


class ProjectUpdateView(UpdateView):
    """ 项目更新  """
    # todo  edit_project
    template_name = 'assets/project_update.html'
    form_class = ProjectForm
    model = Project
    success_url = reverse_lazy('project_list')

    def get_context_data(self, **kwargs):
        business_name = Project.objects.get(pk=self.kwargs.get("pk"))
        user_list_id = []
        dev_group_userlist = []

        try:
            # 获取研发部门object_list
            dev_group = Department_Mode.objects.get(desc_gid=1003)  # todo 硬编码 bug 如果用两个1003则会 报错
            # 获取已在研发部门用户列表
            dev_group_userlist = CustomUser.objects.filter(department_id=dev_group.pk)
        except Exception as e:
            print(e)
            print("没有找到dev_group")

        if business_name.project_user_group:
            # 组成员
            print(business_name.project_user_group)  # todo
            user_list_id = [int(i) for i in ast.literal_eval(business_name.project_user_group)]

        context = {
            'dev_group_userlist': dev_group_userlist,
            'user_list_id': user_list_id,
        }
        kwargs.update(context)
        return super().get_context_data(**kwargs)


class ProjectDeleteView(TemplateView):
    """ 删除项目 """

    # delete_project todo  权限认证

    def get(self, request, *args, **kwargs):
        pk = self.kwargs.get('pk')
        project = get_object_or_404(Project, pk=pk)
        ProjectSwan.objects.filter(project_name_id=pk).delete()  # 发布系统字段
        project.delete()  # 这个删除会删除该业务下的机器

        # todo  异步执行
        """  
        project_name = project.project_name
        ret = zabbix_group_del(project_name)
        if ret == 0:
            pass
        """
        return HttpResponseRedirect(reverse_lazy('project_list'))


@login_required
def seaech_host_by_node_name(request):
    """
    通过主机名搜索
    """

    content = {}
    if request.method == 'POST':
        search_name = request.POST["node_name"]
        node = Host.objects.filter(node_name=search_name).count()
        if node == 0:
            content['ok'] = '主机名可以使用'
            return HttpResponse(json.dumps(content))
        else:
            content['error'] = '主机名已存在'
            return HttpResponse(json.dumps(content))
